/*
 * Copyright (c) 2018-2024 北京华恒盛世科技有限公司
 * QUICKPOOL is licensed under Mulan PSL v2.
 * You can use this software according to the terms and conditions of the Mulan PSL v2.
 * You may obtain a copy of Mulan PSL v2 at:
 *     http://license.coscl.org.cn/MulanPSL2
 * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
 * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
 * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
 * See the Mulan PSL v2 for more details.
*/

#ifndef QUICKPOOL_COMMON_H
#define QUICKPOOL_COMMON_H

#include <unistd.h>
#include <rpc/xdr.h>
#include <netdb.h>
#include <sys/stat.h>
#include <sys/resource.h>

#include "list.h"
#include "limit.h"

#ifndef INFINIT_INT
#define INFINIT_INT    0x7fffffff
#endif

#ifndef INFINIT_LONG
#define INFINIT_LONG    0x7fffffff
#endif

#ifndef INFINIT_FLOAT
#define INFINIT_FLOAT   (float) (0x7fffffff)
#endif

#ifndef INFINIT_LOAD
#define INFINIT_LOAD    (float) (0x7fffffff)
#endif

#ifndef INFINIT_DOUBLE
#define INFINIT_DOUBLE    (double) (0x7fffffffffffffff)
#endif

#define INFINIT_SHORT  0x7fff

#define FLOAT_EQUAL_ZERO(x)  (fabs(x) < 0.001)

#define XDR_OFFSET 4

#ifndef MIN
#define MIN(x,y)  ((x) < (y) ? (x) : (y))
#endif

#ifndef MAX
#define MAX(x,y)        ((x) > (y) ? (x) : (y))
#endif

#define ABS(i) ((i) < 0 ? -(i) : (i))

#ifndef FREEUP
#define FREEUP(p)   if (p != NULL) { \
                        free(p);     \
                        p = NULL;    \
                    }
#endif

#define SKIPSPACE(sp)      while (isspace(*(sp)) && *(sp) != '\0') (sp)++;

#define INTEGER_BITS   32
#define GET_INTNUM(i) ((i)/INTEGER_BITS + 1)

#define SET_BIT(bitNo, integers)           \
    integers[(bitNo)/INTEGER_BITS] |= (1<< (bitNo)%INTEGER_BITS);
#define CLEAR_BIT(bitNo, integers)           \
    integers[(bitNo)/INTEGER_BITS] &= ~(1<< (bitNo)%INTEGER_BITS);
#define TEST_BIT(bitNo, integers, isSet)  \
   {  \
      if (integers[(bitNo)/INTEGER_BITS] & (1<<(bitNo)%INTEGER_BITS))  \
          isSet = TRUE;         \
      else                      \
          isSet = FALSE;        \
   }

extern int timeLevel;
#ifndef RECORD_FUNCTIME
#define RECORD_FUNCTIME(level,func,name)                                \
    { if (timeLevel > level) {                                          \
            struct timeval before, after;                               \
            gettimeofday(&before, NULL);                                \
            func;                                                       \
            gettimeofday(&after, NULL);                                 \
            log_message(INFO, NOCLASS, "L%d %s %d ms",level,name,       \
                        (int)((after.tv_sec - before.tv_sec)*1000 +     \
                              (after.tv_usec-before.tv_usec)/1000));    \
        } else                                                          \
            func;                                                       \
    }
#endif

#define LOG_DEBUG1  LOG_DEBUG + 1
#define LOG_DEBUG2  LOG_DEBUG + 2
#define LOG_DEBUG3  LOG_DEBUG + 3

enum log_level
{
    NOLOG = 0,
    ERR = 1,
    WARNING,
    INFO,
    DEBUG,
    DEBUG2
};

enum log_class 
{
    NOCLASS = 0,
    TRACER = 0x0001,
    PERFM = 0x0002,
    CHANNEL = 0x0004,
    SCHEDULE = 0x0008,
    DEBUGXDR = 0x0010,
    EXECUTE = 0x0020,
    DEBUGSIGNAL = 0x0040,
    DEBUGRES = 0x0080,
    PENDINGREASON = 0x0100,
    FAIRSHARE = 0x0200,
    PREEMPTION = 0x0400,
    TASKSTART = 0x800,
    EVENTFILE = 0x1000,
    JOBGROUP = 0x2000,
};

#define NRM_UNAVAIL  0x00010000
#define NRM_BUSY     0x00020000
#define NRM_CLOSEWIN 0x00040000
#define NRM_OK_MASK  0x001f0000

#define STATUS_ISUNAVAIL(status)     (((status[0]) & NRM_UNAVAIL) != 0)
#define STATUS_ISBUSY(status) (((status[0]) & NRM_BUSY) != 0)
#define STATUS_ISCLOSEWIN(status) (((status[0]) & NRM_CLOSEWIN) != 0)

#define TIMESTRINGLEN 25

#define CTIME_FORMAT_DEFAULT		0
#define CTIME_FORMAT_a_b_d_T_Y		1
#define CTIME_FORMAT_a_b_d_T		3
#define CTIME_FORMAT_b_d_H_M		4
#define CTIME_FORMAT_m_d_Y		5
#define CTIME_FORMAT_H_M_S		6

#define AUTH_IDENT      "ident"
#define AUTH_PARAM_EAUTH  "ua"

#define WILDCARD_STR  "any"
#define LOCAL_STR     "local"

typedef enum {
    R1M,
    R5M,
    R15M,
    UT,
    PG,
    IO,
    TMP,
    SWP,
    MEM,
    USR1,
    USR2
} load_index_t;

typedef struct dayhour {
    short day;
    float hour;
} day_hour_t;

typedef struct timeWindow {
    LIST_T *forw;
    LIST_T *back;
    struct dayhour open_dayhour;
    struct dayhour close_dayhour;
} time_window_t;

struct nameList {
    unsigned int num_name;
    unsigned int size;
    char **names;
};

#define PRINT_SHORT_NAMELIST  0x01
#define PRINT_MCPU_HOSTS      0x04
struct admins {
    unsigned int num_admins;
    uid_t *admin_ids;
    uid_t *admin_gids;
    char **admin_names;
};

/* daemon.c */
extern void save_daemon_path(char *);
extern char *get_daemon_path(const char *, char *, char *);
extern void daemonize_myself(void);

/* string.c */
extern char *copy_string(const char *);
extern bool_t askfor_confirm(char *);
extern char *get_string_token(char **, const char *, char *, size_t);
extern char *get_string_inside(char **, char, char);
extern bool_t has_name_inlist(char *,  char **, int);
extern char *ctime_2string(int, const time_t *, char *);
extern char *cputimer_2string(float, char *);
extern int strip_quotes(char *, char *);
extern int add_quotes(FILE *, char *);
extern void strip_newline(char *);
extern char *strip_allspaces(const char *);
extern char *strip_spaces(char *, bool_t);
extern struct nameList *new_namelist(unsigned int);
extern struct nameList *merge_namelist(struct nameList *, struct nameList *);
extern struct nameList *string_2namelist(char **, unsigned int);
extern struct nameList *longstring_2namelist(char *);
extern int add_member_2namelist(char *, struct nameList *);
extern char *namelist_2string(struct nameList *);
extern void free_namelist(struct nameList *);
extern void free_string_array(char **, int);
extern bool_t isinteger(const char *);
extern bool_t isnumber(const char *);
extern bool_t islong(char *);
extern bool_t isdigit_string(char *);
extern bool_t issame_host(const char *, const char *);
extern int gf_atoi(char *, int, int);
extern float gf_atof(char *, float, float);
extern char *gf_get_line(FILE *, unsigned int *, char *);

/* id.c */
extern char *getmy_uname(void);
extern char *get_uname(uid_t);
extern uid_t get_uid(const char *, uid_t *);
extern uid_t change_uid(uid_t);
extern struct passwd *get_user_byname(const char *);
extern struct group *get_group_byname(const char *);

/* signal.c */
typedef void (*SIGFUNCTYPE)(int);
extern void (*Signal_(int, void (*)(int)))(int);
extern int gf_block_allsignals(sigset_t *, sigset_t *);
extern int gf_block_signals(int, sigset_t *, sigset_t *);
extern void gf_unblock_signals(sigset_t*);
extern int gf_string_2signal(const char *);
extern char *gf_signal_2string(int);

/* dir.c */
extern char *gf_getwd(char *);
extern bool_t gf_isfullpath(const char *);

/* log.c */
extern int gf_set_logclass(const char *);
extern void gf_set_intlogclass(int);
extern void gf_set_timinglog(unsigned int);
extern void gf_set_loglevel(const char *);
extern int gf_get_logclass(void);
extern void gf_set_ignorewarn(int);
extern char *loglevel2string(int, char *);
extern void close_log(void);
extern int open_log(const char *, const char *, unsigned int);
extern void log_message(enum log_level, enum log_class, const char *, ...);

/* misc.c */
extern int gf_setenv(const char *, char *);

/* conf.c */
extern int is_admin(char **, char *, int);
extern int addmore_admins(char *, struct admins *, unsigned int *);

/* limit.c */
extern void init_resource_limit(int []);
extern void set_resource_limit(struct resourceLimit *, struct rlimit *, int);
extern int is_limitok(int *);

/* time.c */
extern time_t optarg_2time(char *);
extern char *parse_time_window(char *, LIST_T *, const char *);
extern bool_t iswindow_active(struct dayhour *, time_t, time_t *, LIST_T *);
extern void set_dayhour_4time(struct dayhour *, time_t);

/* host.c */
extern void gf_set_hostfile(const char *);
extern struct addrinfo *gf_hostname(const char *, int);
extern struct hostent *gf_gethostbyname(const char *);
extern struct hostent *gf_gethostbyaddr(in_addr_t *, socklen_t, int);


#endif
